﻿using CloOpenSDK;
using Microsoft.Extensions.Logging;
using Sino.CapacityCloud.Repositories.Models;
using Sino.CapacityCloud.Services.Models;
using Sino.Common.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Sino.CapacityCloud.Services
{

    public class CaptchasService
        : ICaptchasService
    {

        private readonly ILogger m_logger;
        private readonly ApplicationDbContext m_dbContext;
        private readonly ISmsSender m_smsSender;
        private readonly ICaptchasGenerator m_captchasGenerator;

        public CaptchasService(ApplicationDbContext dbContext, ISmsSender smsSender, ICaptchasGenerator captchasGenerator, ILoggerFactory loggerFactory)
        {
            this.m_logger = loggerFactory.CreateLogger<CaptchasService>();
            this.m_dbContext = dbContext;
            this.m_smsSender = smsSender;
            this.m_captchasGenerator = captchasGenerator;
        }

        public async Task<bool> SendCaptchasAsync(string phoneNumber, CaptchasType type = CaptchasType.UserLogin)
        {
            if (!phoneNumber.IsPhoneNumber())
            {
                throw new ArgumentOutOfRangeException("phoneNumber");
            }
            var successCode = (int)SmsRequestResult.Success;
            var lastSmsCode = this.m_dbContext.SmsCodes
                .OrderBy(x => x.CreationTime)
                .LastOrDefault(x =>
                    x.PhoneNumber == phoneNumber &&
                    x.StatusCode == successCode);
            //if (lastSmsCode != null && lastSmsCode.IsValid && (DateTime.Now - lastSmsCode.CreationTime).TotalMinutes < 1)
            //{
            //    //if (lastSmsCode != null && lastSmsCode.IsValid)
            //    //{
            //        throw new SystemException("The last captchas request is still valid.");
            //    //}
            //}
            try
            {
                var code = await this.m_captchasGenerator.GenerateCaptchasAsync();
                var result = await this.m_smsSender.SendSmsAsync(phoneNumber, code);
                var smsCodeEntity = new SmsCode()
                {
                    Code = code,
                    PhoneNumber = phoneNumber,
                    StatusCode = (int)result,
                };
                this.m_dbContext.SmsCodes.Add(smsCodeEntity);
                this.m_dbContext.SaveChanges();
                if (result == SmsRequestResult.Success)
                {
                    return await Task.FromResult(true);
                }
                else
                {
                    this.m_logger.LogError($"Failed to send captchas sms with code {result}.");
                    return await Task.FromResult(false);
                }
            }
            catch (Exception ex)
            {
                this.m_logger.LogError(ex.Message, ex);
                throw new Exception(ex.Message + ex.InnerException?.Message, ex);
            }
        }

        public async Task<bool> ValidateCaptchasAsync(string phoneNumber, string captchas)
        {
            if (!phoneNumber.IsPhoneNumber())
            {
                throw new ArgumentOutOfRangeException("phonNumber");
            }
            var lastSmsCode = this.m_dbContext.SmsCodes.OrderBy(x => x.CreationTime).LastOrDefault(x => x.PhoneNumber == phoneNumber);
            if (lastSmsCode != null && lastSmsCode.IsValid && lastSmsCode.Code == captchas)
            {
                return await Task.FromResult(true);
            }
            return await Task.FromResult(false);
        }

    }

}